class Element {
  constructor(node, ctx) {
    this.ctx = ctx
    this.layoutNode = node
  }

  computeMatrix(a, b, c, d, e, f) {
    function rotate(a, b, c, d, e, f) {
      var aa = Math.round((180 * Math.asin(a)) / Math.PI)
      var bb = Math.round((180 * Math.acos(b)) / Math.PI)
      var cc = Math.round((180 * Math.asin(c)) / Math.PI)
      var dd = Math.round((180 * Math.acos(d)) / Math.PI)
      var deg = 0
      if (aa == bb || -aa == bb) {
        deg = dd
      } else if (-aa + bb == 180) {
        deg = 180 + cc
      } else if (aa + bb == 180) {
        deg = 360 - cc || 360 - dd
      }
      return deg >= 360 ? 0 : deg
    }
    let translate = {
      x: e,
      y: f,
    }
    let scale = {
      x: a,
      y: d,
    }
    return { translate, scale, rotate: rotate(a, b, c, d, e, f) }
  }

  transfer() {
    let { style } = this.layoutNode
    let transform = style.transform
    const transformFun = new Function(
      `function matrix(a,b,c,d,e,f){return {a,b,c,d,e,f}}return ${transform}`
    )
    let matrix = transformFun()
    return this.computeMatrix(matrix.a, matrix.b, matrix.c, matrix.d, matrix.e, matrix.f)
  }

  parseTextNodeMatrix() {
    let { react, style, text } = this.layoutNode

    if (style.transform && style.transform !== 'none') {
      let transformation = this.transfer()

      this.ctx.translate(react.left + react.width / 2, react.top + react.height / 2)
      this.ctx.rotate((Math.PI / 180) * -transformation.rotate)
      this.ctx.translate(-react.left - react.width / 2, -react.top - react.height / 2)
    } else {
      // this.ctx.setTransform(1, 0, 0, 1, 0, 0)
    }
  }

  parseNodeMatrix() {
    let { react, style, text } = this.layoutNode

    if (style.transform && style.transform !== 'none') {
      let transformation = this.transfer()

      this.ctx.translate(react.left + react.width / 2, react.top + react.height / 2)
      this.ctx.rotate((Math.PI / 180) * transformation.rotate)

      this.ctx.translate(-react.left - react.width / 2, -react.top - react.height / 2)
    } else {
      // this.ctx.setTransform(1, 0, 0, 1, 0, 0)
    }
  }

  roundedRect(x, y, width, height, radius, color, style = 'solid', stroke, fill) {
    let lineWidth = this.ctx.lineWidth
    if (style === 'dotted') {
      this.ctx.setLineDash([lineWidth, lineWidth])
    } else if (style === 'dashed') {
      this.ctx.setLineDash([4 * lineWidth, 4 * lineWidth])
    }
    x += lineWidth / 2
    y += lineWidth / 2
    width -= lineWidth
    height -= lineWidth
    this.ctx.save()

    this.ctx.beginPath()
    this.ctx.strokeStyle = color
    this.ctx.moveTo(x, y + radius)
    this.ctx.lineTo(x, y + height - radius)
    this.ctx.quadraticCurveTo(x, y + height, x + radius, y + height)
    this.ctx.lineTo(x + width - radius, y + height)
    this.ctx.quadraticCurveTo(x + width, y + height, x + width, y + height - radius)
    this.ctx.lineTo(x + width, y + radius)
    this.ctx.quadraticCurveTo(x + width, y, x + width - radius, y)
    this.ctx.lineTo(x + radius, y)
    this.ctx.quadraticCurveTo(x, y, x, y + radius)
    this.ctx.closePath()
    if (stroke) {
      this.ctx.stroke()
    }
    if (fill) {
      this.ctx.fill()
    }

    this.ctx.setLineDash([])
    this.ctx.restore()
  }
}
